package com.jianguozh.difs.support.api.ops;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jianguozh.difs.common.bean.R;
import com.jianguozh.difs.framework.base.BaseController;
import com.jianguozh.difs.framework.constant.SecurityConstant;
import com.jianguozh.difs.framework.validator.group.AddGroup;
import com.jianguozh.difs.framework.validator.group.UpdateGroup;
import com.jianguozh.difs.support.api.ops.dto.RoleClientResDto;
import com.jianguozh.difs.support.api.ops.dto.RoleDto;
import com.jianguozh.difs.support.service.sys.entity.Client;
import com.jianguozh.difs.support.service.sys.entity.Res;
import com.jianguozh.difs.support.service.sys.entity.Role;
import com.jianguozh.difs.support.service.sys.service.IRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * <p>
 * 角色 前端控制器
 * </p>
 *
 * @author hanrs
 * @since 2022-03-17
 */
@RestController
@RequestMapping("/role")
public class RoleController extends BaseController {

    @Autowired
    IRoleService roleService;

    /**
     * 由id获取对象
     */
    @GetMapping("/{id}")
    public R<Role> get(@PathVariable String id) {
        return success(roleService.getById(id));
    }

    /**
     * 新增
     */
    @PreAuthorize("hasAnyAuthority('" + SecurityConstant.AUTHORITY_TAG_OPS + "')")
    @PostMapping("")
    public R<Role> add(@RequestBody @Validated(value = {AddGroup.class}) RoleDto roleDto) {
        long count = roleService.count(new LambdaQueryWrapper<Role>().eq(Role::getRoleName, roleDto.getRoleName()));
        if (count > 0) {
            return failed("已经存在名字'" + roleDto.getRoleName() + "'的角色.");
        }

        Role entity = new Role();
        BeanUtil.copyProperties(roleDto, entity);
        boolean result = roleService.saveOrUpdate(entity);
        return result ? success(entity) : failed("操作失败.");
    }

    /**
     * 修改
     */
    @PreAuthorize("hasAnyAuthority('" + SecurityConstant.AUTHORITY_TAG_OPS + "')")
    @PutMapping("")
    public R<Role> modify(@RequestBody @Validated(value = {UpdateGroup.class}) RoleDto roleDto) {
        long count = roleService.count(new LambdaQueryWrapper<Role>().eq(Role::getRoleName, roleDto.getRoleName()).ne(Role::getId, roleDto.getId()));
        if (count > 0) {
            return failed("已经存在'" + roleDto.getRoleName() + "'的角色.");
        }

        Role entity = new Role();
        BeanUtil.copyProperties(roleDto, entity);
        boolean result = roleService.saveOrUpdate(entity);
        return result ? success(entity) : failed("操作失败.");
    }

    /**
     * 单个删除
     */
    @PreAuthorize("hasAnyAuthority('" + SecurityConstant.AUTHORITY_TAG_OPS + "')")
    @DeleteMapping("/{id}")
    public R<Boolean> delete(@PathVariable String id) {
        boolean result = roleService.removeById(id);
        return result ? success(true) : failed("操作失败.");
    }

    /**
     * 条件分页查询
     */
    @GetMapping("/page-query")
    public R<IPage<Role>> pageQuery(HttpServletRequest request,
                                    @RequestParam(name = "roleName", required = false) String roleName
    ) {

        LambdaQueryWrapper<Role> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(roleName))
            lambdaQueryWrapper.like(Role::getRoleName, roleName);

        IPage page = resolvePage(request);
        return success(roleService.page(page, lambdaQueryWrapper));
    }

    /**
     * 获取角色被授予的应用
     *
     * @param roleId
     * @return
     */
    @GetMapping("/granted-client")
    public R<List<Client>> listGrantedClient(@RequestParam(name = "roleId") String roleId) {
        return success(roleService.listGrantedClient(roleId));
    }

    /**
     * 获取角色被授予的应用的资源
     *
     * @param roleId
     * @param clientId
     * @return
     */
    @GetMapping("/granted-res")
    public R<List<Tree<String>>> listGrantedRes(@RequestParam(name = "roleId") String roleId,
                                                @RequestParam(name = "clientId") String clientId) {
        List<Res> resList = roleService.listGrantedRes(roleId, clientId);
        TreeNodeConfig config = new TreeNodeConfig();
        config.setWeightKey("sort").setParentIdKey("parentId").setIdKey("id").setChildrenKey("children");
        List<Tree<String>> trees = TreeUtil.build(resList, null, config, (obj, tree) -> {
            tree.setParentId(obj.getParentId());
            tree.setId(obj.getId());
            tree.putExtra("key", obj.getId());
            tree.putExtra("sort", obj.getSort());
            tree.putExtra("parentKey", obj.getParentId());
            tree.putExtra("clientId", obj.getClientId());
            tree.putExtra("title", obj.getResName());
            tree.putExtra("badge", obj.getBadge());
            tree.putExtra("icon", obj.getIcon());
            tree.putExtra("path", obj.getPath());
            tree.putExtra("component", obj.getComponent());
            tree.putExtra("permission", obj.getPermission());
        });
        return success(trees);
    }

    /**
     * 获取应用可分配的角色
     *
     * @param clientId
     * @return
     */
    @GetMapping("/allow-grant")
    public R<List<Role>> listAllowGrant(@RequestParam(name = "clientId") String clientId) {
        return success(roleService.listByClientId(clientId));
    }

    /**
     * 保存角色授予的应用和资源
     *
     * @param roleClientResDto
     * @return
     */
    @PreAuthorize("hasAnyAuthority('" + SecurityConstant.AUTHORITY_TAG_OPS + "')")
    @PutMapping("/grant-client-and-res")
    public R<Boolean> saveGrantedClientAndRes(@RequestBody @Validated RoleClientResDto roleClientResDto) {
        roleService.saveGrantedClientAndRes(roleClientResDto.getRoleId(), roleClientResDto.getClientId(), roleClientResDto.getGranted(), roleClientResDto.getResIds());
        return success(true);
    }

    /**
     * 获取所有
     *
     * @return
     */
    @GetMapping("/all")
    public R<List<Role>> getAll() {
        return success(roleService.list());
    }


}
